package server

import (
	"bbs-go/internal/controllers/admin"
	"bbs-go/internal/controllers/api"
	"bbs-go/internal/middleware"
	"bbs-go/internal/pkg/config"
	"bbs-go/internal/pkg/room"
	"log/slog"
	"os"
	"path/filepath"
	"strings"

	"github.com/gorilla/websocket"
	"github.com/iris-contrib/middleware/cors"
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/mvc"

	"github.com/mlogclub/simple/web"

	"github.com/kataras/iris/v12/middleware/logger"
	"github.com/kataras/iris/v12/middleware/recover"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

func NewServer() {
	app := iris.New()
	app.Logger().SetLevel("warn")
	app.Use(recover.New())
	app.Use(logger.New())
	app.Use(cors.New(cors.Options{
		AllowedOrigins:   []string{"*"}, // allows everything, use that to change the hosts.
		AllowCredentials: true,
		MaxAge:           600,
		AllowedMethods:   []string{iris.MethodGet, iris.MethodPost, iris.MethodOptions, iris.MethodHead, iris.MethodDelete, iris.MethodPut},
		AllowedHeaders:   []string{"*"},
	}))
	app.AllowMethods(iris.MethodOptions)

	app.OnAnyErrorCode(func(ctx iris.Context) {
		path := ctx.Path()
		var err error
		if strings.Contains(path, "/api/admin/") {
			err = ctx.JSON(web.JsonErrorCode(ctx.GetStatusCode(), "Http error"))
		}
		if err != nil {
			slog.Error(err.Error(), slog.Any("err", err))
		}
	})

	// 设置静态文件处理
	app.Handle("GET", "/images/{params:path}", func(Ctx iris.Context) {
		p := Ctx.Params()
		file := p.Get("params")
		fullPath := filepath.Join("./data/images/", file)
		Ctx.SendFile(fullPath, filepath.Base(file))
	})

	// 设置静态文件处理
	app.Handle("GET", "/resources/{params:path}", func(Ctx iris.Context) {
		p := Ctx.Params()
		file := p.Get("params")
		fullPath := filepath.Join("./data/resources/", file)
		Ctx.SendFile(fullPath, filepath.Base(file))
	})

	room.GlobalRoom = room.NewRoom()
	go room.GlobalRoom.Run()

	conf := config.Instance

	// api
	mvc.Configure(app.Party("/api"), func(m *mvc.Application) {
		m.Party("/topic").Handle(new(api.TopicController))
		m.Party("/article").Handle(new(api.ArticleController))
		m.Party("/login").Handle(new(api.LoginController))
		m.Party("/user").Handle(new(api.UserController))
		m.Party("/user-department").Handle(new(api.UserDepartmentController))
		m.Party("/tag").Handle(new(api.TagController))
		m.Party("/comment").Handle(new(api.CommentController))
		m.Party("/favorite").Handle(new(api.FavoriteController))
		m.Party("/like").Handle(new(api.LikeController))
		m.Party("/checkin").Handle(new(api.CheckinController))
		m.Party("/config").Handle(new(api.ConfigController))
		m.Party("/upload").Handle(new(api.UploadController))
		m.Party("/link").Handle(new(api.LinkController))
		m.Party("/captcha").Handle(new(api.CaptchaController))
		m.Party("/search").Handle(new(api.SearchController))
		m.Party("/fans").Handle(new(api.FansController))
		m.Party("/user-report").Handle(new(api.UserReportController))
		m.Party("/chat-friends").Handle(new(api.ChatFriendsController))
		m.Party("/chat-groups").Handle(new(api.ChatGroupsController))
		m.Party("/chat-socket").Handle(new(api.ChatSocketController))
		m.Party("/index-category").Handle(new(api.IndexCategoryController))
		m.Party("/index-article").Handle(new(api.IndexArticleController))
		m.Party("/resources").Handle(new(api.ResourcesController))
		m.Party("/system-notice").Handle(new(api.SystemNoticeController))
	})

	// admin
	mvc.Configure(app.Party("/api/admin"), func(m *mvc.Application) {
		m.Router.Use(middleware.AdminAuth)
		m.Party("/common").Handle(new(admin.CommonController))
		m.Party("/user").Handle(new(admin.UserController))
		m.Party("/tag").Handle(new(admin.TagController))
		m.Party("/article").Handle(new(admin.ArticleController))
		m.Party("/comment").Handle(new(admin.CommentController))
		m.Party("/favorite").Handle(new(admin.FavoriteController))
		m.Party("/article-tag").Handle(new(admin.ArticleTagController))
		m.Party("/topic").Handle(new(admin.TopicController))
		m.Party("/topic-node").Handle(new(admin.TopicNodeController))
		m.Party("/sys-config").Handle(new(admin.SysConfigController))
		m.Party("/link").Handle(new(admin.LinkController))
		m.Party("/user-score-log").Handle(new(admin.UserScoreLogController))
		m.Party("/operate-log").Handle(new(admin.OperateLogController))
		m.Party("/user-report").Handle(new(admin.UserReportController))
		m.Party("/forbidden-word").Handle(new(admin.ForbiddenWordController))
		m.Party("/index-category").Handle(new(admin.IndexCategoryController))
		m.Party("/index-article").Handle(new(admin.IndexArticleController))
		m.Party("/resources").Handle(new(admin.ResourcesController))
		m.Party("/resources-types").Handle(new(admin.ResourcesTypesController))
		m.Party("/approval-template").Handle(new(admin.ApprovalTemplateController))
		m.Party("/user-department").Handle(new(admin.UserDepartmentController))
		m.Party("/system-notice").Handle(new(admin.SystemNoticeController))
		m.Party("/user-login-log").Handle(new(admin.UserLoginLogController))

		m.Party("/role").Handle(new(admin.RoleController))
		m.Party("/menu").Handle(new(admin.MenuController))
	})

	if err := app.Listen(":"+conf.Port,
		iris.WithConfiguration(iris.Configuration{
			DisableStartupLog:                 false,
			DisableInterruptHandler:           false,
			DisablePathCorrection:             false,
			EnablePathEscape:                  false,
			FireMethodNotAllowed:              false,
			DisableBodyConsumptionOnUnmarshal: false,
			DisableAutoFireStatusCode:         false,
			EnableOptimizations:               true,
			TimeFormat:                        "2006-01-02 15:04:05",
			Charset:                           "UTF-8",
		}),
	); err != nil {
		slog.Error(err.Error(), slog.Any("err", err))
		os.Exit(-1)
	}
}

// var (
// 	clients   = make(map[*websocket.Conn]bool)
// 	broadcast = make(chan Message)
// 	upgrader  = websocket.Upgrader{
// 		CheckOrigin: func(r *http.Request) bool {
// 			return true
// 		},
// 	}
// 	mu sync.Mutex
// )

// type Message struct {
// 	ReceiverId int    `json:"receiverId"`
// 	Content    string `json:"content"`
// }

// func serveWs(w http.ResponseWriter, r *http.Request) {
// 	conn, err := upgrader.Upgrade(w, r, nil)
// 	if err != nil {
// 		log.Println("Upgrade error:", err)
// 		return
// 	}
// 	defer conn.Close()

// 	mu.Lock()
// 	clients[conn] = true
// 	mu.Unlock()

// 	for {
// 		var msg Message
// 		err := conn.ReadJSON(&msg)
// 		if err != nil {
// 			log.Printf("Read error: %v", err)
// 			mu.Lock()
// 			delete(clients, conn)
// 			mu.Unlock()
// 			break
// 		}
// 		broadcast <- msg
// 	}
// }

// func handleMessages() {
// 	for {
// 		msg := <-broadcast
// 		mu.Lock()
// 		for client := range clients {
// 			err := client.WriteJSON(msg)
// 			if err != nil {
// 				log.Printf("Write error: %v", err)
// 				client.Close()
// 				delete(clients, client)
// 			}
// 		}
// 		mu.Unlock()
// 	}
// }
